﻿using System;
using System.ComponentModel;
using System.IO;
using System.Web;
using System.Web.UI;
using Ue.Components.PropertyMappings;

namespace Ue.Infrastructure.UI.SkinnedControls
{
    [ParseChildren(true)]
    /// <summary>
    /// 皮肤控件基类
    /// </summary>
    public abstract class SkinnedControl : Control, INamingContainer
    {
        #region 成员字段、构造方法、虚拟方法

        public event EventHandler<SkinnedEventArgs> InitializeSkined;
        public event EventHandler<SkinnedEventArgs> PreInitializeSkin;

        protected SkinnedControl()
        {
            this.TagName = HtmlTextWriterTag.Div;
            this.IsRenderTag = false;
        }

        protected abstract void InitializeSkin(Control skin);

        #endregion

        protected virtual string GetDefaultSkinFileName()
        {
            var path = HttpContext.Current.Request.Path.TrimStart('~');
            return string.Format("/Themes/Skins{0}", Path.ChangeExtension(path, "ascx"));
        }

        #region 子控件创建
        /// <summary>
        /// This event handler adds the children controls.
        /// </summary>
        protected override void CreateChildControls()
        {
            Control skin = null;

            if (this.SkinTemplate != null)
            {
                this.SkinTemplate.InstantiateIn(this);
                skin = this;
            }
            else
            {
                skin = Page.LoadControl(string.IsNullOrEmpty(this.SkinFileName) ? this.GetDefaultSkinFileName() : this.SkinFileName);

                SkinnedUserControl userControl = skin as SkinnedUserControl;
                if (userControl != null)
                {
                    userControl.Parent = this;
                }
            }

            if (skin != this)
            {
                //先把控件加入到Controls中后再调用InitializeSkin初始化控件。
                //因为控件只有加入之后才能完成整个生存周期，例如子控件的OnInit事件就是在子控件加入到Controls时执行的。
                this.Controls.Add(skin);
            }

            if (skin != null)
            {
                if (EnablePropertyMappings)
                {
                    PropertyMappingHelper.MappingProperties(skin, this.Context);
                }

                var skinnedEventArgs=new SkinnedEventArgs(skin);

                if (this.PreInitializeSkin != null)
                {
                    this.PreInitializeSkin(this, skinnedEventArgs);
                }

                this.InitializeSkin(skin);

                if (this.InitializeSkined != null)
                {
                    this.InitializeSkined(this, skinnedEventArgs);
                }
            }
        }

        public override void RenderControl(HtmlTextWriter writer)
        {
            if (!Visible)
            {
                return;
            }

            if (this.IsRenderTag)
            {
                if (!string.IsNullOrEmpty(Style))
                    writer.AddAttribute(HtmlTextWriterAttribute.Style, Style);
                if (!string.IsNullOrEmpty(Class))
                    writer.AddAttribute(HtmlTextWriterAttribute.Class, Class);
                writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
                writer.RenderBeginTag(TagName);
                base.RenderControl(writer);
                writer.RenderEndTag();
            }
            else
            {
                base.RenderControl(writer);
            }
        }

        #endregion

        #region 公有属性

        [Browsable(false)]
        [TemplateContainer(typeof(SkinnedControl))]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public ITemplate SkinTemplate { get; set; }

        public string SkinFileName { get; set; }

        public HtmlTextWriterTag TagName { get; set; }

        public bool IsRenderTag { get; set; }

        public string Style { get; set; }

        public string Class { get; set; }

        #endregion

        public bool EnablePropertyMappings { get; set; }
    }
}
